﻿using SolidWorks.Interop.cosworks;
using SolidWorks.Interop.sldworks;
using SolidWorks.Interop.swconst;
using SwParaPlatform2.logger;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
using View = SolidWorks.Interop.sldworks.View;

namespace SwParaPlatform2
{
    public class DrawingManager
    {
        private static DrawingManager instance;
        private static readonly object lockObj = new object();
        private ISldWorks swApp;

        // 私有构造函数，防止外部实例化
        private DrawingManager(ISldWorks app)
        {
            swApp = app;
        }

        /// <summary>
        /// 获取单例实例
        /// </summary>
        public static DrawingManager GetInstance(ISldWorks app)
        {
            if (instance == null)
            {
                lock (lockObj)  // 确保线程安全
                {
                    if (instance == null)
                    {
                        instance = new DrawingManager(app);
                        Logger.Instance.Log("DrawingManager 单例已创建");
                    }
                }
            }
            return instance;
        }

        /// <summary>
        /// 获取所有相关的工程图文件列表
        /// </summary>
        public List<string> GetDrawingFiles()
        {
            List<string> drawingFiles = new List<string>();

            IModelDoc2 activeDoc = swApp.ActiveDoc;
            if (activeDoc == null)
            {
                Logger.Instance.Log("没有激活的文档");
                return drawingFiles;
            }

            string modelPath = activeDoc.GetPathName();
            if (string.IsNullOrEmpty(modelPath))
            {
                Logger.Instance.Log("无法获取当前文档路径");
                return drawingFiles;
            }

            swDocumentTypes_e docType = (swDocumentTypes_e)activeDoc.GetType();

            // 判断是零件还是装配体
            if (docType == swDocumentTypes_e.swDocPART || docType == swDocumentTypes_e.swDocASSEMBLY)
            {
                // 1. 添加当前文档的工程图（如果存在）
                AddDrawingToList(modelPath, drawingFiles);

                // 2. 如果是装配体，递归遍历其所有关联零部件
                if (docType == swDocumentTypes_e.swDocASSEMBLY)
                {
                    IAssemblyDoc assembly = (IAssemblyDoc)activeDoc;
                    TraverseComponents(assembly, drawingFiles);
                }
            }
            else
            {
                Logger.Instance.Log("当前文档不是零件或装配体");
            }

            return drawingFiles;
        }

        /// <summary>
        /// 递归遍历装配体中的所有零部件
        /// </summary>
        private void TraverseComponents(IAssemblyDoc assembly, List<string> drawingFiles)
        {
            object[] components = assembly.GetComponents(true);

            foreach (object compObj in components)
            {
                Component2 comp = (Component2)compObj;
                int suppressionState = comp.GetSuppression();
                if (suppressionState == (int)swComponentSuppressionState_e.swComponentLightweight ||
                    suppressionState == (int)swComponentSuppressionState_e.swComponentFullyLightweight ||
                    suppressionState == (int)swComponentSuppressionState_e.swComponentSuppressed)
                {
                    ResolvedComponent(comp);
                }
                string compPath = comp.GetPathName();
                if (!string.IsNullOrEmpty(compPath))
                {
                    // 递归处理子装配体
                    //ModelDoc2 modelDoc = GetModelDocSafe(comp);
                    ModelDoc2 modelDoc = comp.IGetModelDoc();
                    if (modelDoc != null)
                    {
                        swDocumentTypes_e docType = (swDocumentTypes_e)modelDoc.GetType();
                        if (docType == swDocumentTypes_e.swDocASSEMBLY)
                        {
                            AddDrawingToList(compPath, drawingFiles); // 添加零件的工程图
                            IAssemblyDoc subAssembly = (IAssemblyDoc)modelDoc;
                            TraverseComponents(subAssembly, drawingFiles); // 递归遍历子装配体
                        }
                        else if (docType == swDocumentTypes_e.swDocPART)
                        {
                            AddDrawingToList(compPath, drawingFiles); // 添加零件的工程图
                        }
                    }
                }
                comp.SetSuppression2(suppressionState);
            }
        }

        private void ResolvedComponent(Component2 component)
        {
            Logger.Instance.Log("组件处于轻化模式，尝试将其解析...");
            try
            {
                // 设置为已解析状态
                int status = component.SetSuppression2((int)swComponentSuppressionState_e.swComponentResolved);
                if (status == (int)swSuppressionError_e.swSuppressionChangeOk)
                {
                    Logger.Instance.Log("组件成功解析！");
                }
                else
                {
                    Logger.Instance.Log("解析组件失败！");
                }
            }
            catch (Exception ex)
            {
                Logger.Instance.Log("解析轻化组件时出错：" + ex.Message);
            }
        }

        /// <summary>
        /// 检查和获取模型文档（包括加载未加载的组件）
        /// </summary>
        private ModelDoc2 GetModelDocSafe(Component2 component)
        {
            ModelDoc2 modelDoc = component.IGetModelDoc();

            // 如果模型文档为空，尝试加载
            if (modelDoc == null)
            {
                Logger.Instance.Log("组件未加载，尝试加载...");

                // 检查是否处于轻化模式
                int suppressionState = component.GetSuppression();
                if (suppressionState == (int)swComponentSuppressionState_e.swComponentLightweight ||
                    suppressionState == (int)swComponentSuppressionState_e.swComponentFullyLightweight ||
                    suppressionState == (int)swComponentSuppressionState_e.swComponentSuppressed)
                {
                    Logger.Instance.Log("组件处于轻化模式，尝试将其解析...");
                    try
                    {
                        // 设置为已解析状态
                        int status = component.SetSuppression2((int)swComponentSuppressionState_e.swComponentResolved);
                        if (status == (int)swSuppressionError_e.swSuppressionChangeOk)
                        {
                            Logger.Instance.Log("组件成功解析！");
                            modelDoc = component.IGetModelDoc();
                        }
                        else
                        {
                            Logger.Instance.Log("解析组件失败！");
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.Instance.Log("解析轻化组件时出错：" + ex.Message);
                    }
                }

                // 直接打开
                string path = component.GetPathName();
                ModelDoc2 CompDoc = component.GetModelDoc2();
                int docType = (int)CompDoc.GetType();
                if (!string.IsNullOrEmpty(path))
                {
                    Logger.Instance.Log("直接打开模型文件：" + path);
                    int Errors = 0;
                    int Warnings = 0;
                    modelDoc = swApp.OpenDoc6(
                        path,
                        (int)docType,
                        (int)swOpenDocOptions_e.swOpenDocOptions_Silent, "", ref Errors, ref Warnings);
                    Logger.Instance.Log($"解析工程图时打开零部件文档:{path}, Errors = {Errors}, Warnings = {Warnings}");
                }
                component.SetSuppression2(suppressionState);

                if (modelDoc == null)
                {
                    Logger.Instance.Log("模型加载失败！");
                }
            }
            return modelDoc;
        }



        // 添加工程图文件路径到列表
        private void AddDrawingToList(string modelPath, List<string> drawingFiles)
        {
            string drawingPath = FindDrawingFile(modelPath);
            if (!string.IsNullOrEmpty(drawingPath) && !drawingFiles.Contains(drawingPath))
            {
                drawingFiles.Add(drawingPath);
                Logger.Instance.Log($"找到工程图：{drawingPath}");
            }
        }

        // 查找工程图文件
        private string FindDrawingFile(string modelPath)
        {
            string modelDirectory = Path.GetDirectoryName(modelPath);
            string fileNameWithoutExt = Path.GetFileNameWithoutExtension(modelPath);

            // 工程图文件路径（假定工程图与模型在同一路径）
            string drawingPath = Path.Combine(modelDirectory, fileNameWithoutExt + ".slddrw");
            if (File.Exists(drawingPath))
            {
                return drawingPath;
            }

            return null;
        }

        /// <summary>
        /// 按顺序打开工程图
        /// </summary>
        public void OpenDrawingsInOrder(List<string> drawingFiles)
        {
            foreach (string drawingPath in drawingFiles)
            {
                Logger.Instance.Log($"打开工程图：{drawingPath}");
                IModelDoc2 drawingDoc = (IModelDoc2)swApp.OpenDoc6(
                    drawingPath,
                    (int)swDocumentTypes_e.swDocDRAWING,
                    (int)swOpenDocOptions_e.swOpenDocOptions_Silent,
                    "", 0, 0);

                if (drawingDoc != null)
                {
                    // 执行接口C
                    InterfaceC(drawingDoc);

                    Logger.Instance.Log($"已关闭工程图：{drawingDoc.GetTitle()}");
                    // 关闭工程图
                    swApp.CloseDoc(drawingDoc.GetTitle());
                    
                }
                else
                {
                    Logger.Instance.Log($"无法打开工程图：{drawingPath}");
                }
            }
        }

        // 接口C：打印信息（后续可扩展）
        private void InterfaceC(IModelDoc2 drawingDoc)
        {
            Logger.Instance.Log($"接口C触发：工程图 {drawingDoc.GetTitle()} 已打开");
        }

        /// <summary>
        /// 复制工程图文件并更新引用
        /// </summary>
        public void CopyAndAssociateDrawing(string oldModelPath, string newModelPath)
        {
            try
            {
                // 1. 查找旧路径中的工程图文件C
                string drawingPath = FindDrawingFile(oldModelPath);
                if (string.IsNullOrEmpty(drawingPath))
                {
                    Logger.Instance.Log($"未找到工程图文件：{oldModelPath}");
                    return;
                }

                // 2. 生成新路径D
                string newDirectory = Path.GetDirectoryName(newModelPath);
                string newFileName = Path.GetFileName(drawingPath);
                string newDrawingPath = Path.Combine(newDirectory, newFileName);

                // 3. 复制工程图文件C到D路径
                try
                {
                    File.Copy(drawingPath, newDrawingPath, true);
                    Logger.Instance.Log($"工程图文件复制成功：{newDrawingPath}");
                }
                catch (IOException ex)
                {
                    Logger.Instance.Log($"文件复制失败：{ex.Message}");
                    return;
                }

                // 4. 更新工程图D中的模型引用为B
                //if (UpdateDrawingReference(newDrawingPath, newModelPath, oldModelPath))
                //{
                //    Logger.Instance.Log($"工程图文件已成功更新引用：{newDrawingPath} <-> {newModelPath}");
                //}
                //else
                //{
                //    Logger.Instance.Log($"更新引用失败：{newDrawingPath} <-> {newModelPath}");
                //}
            }
            catch (Exception ex)
            {
                Logger.Instance.Log($"复制和关联工程图时出现错误：{ex.Message}");
            }
        }

        /// <summary>
        /// 更新工程图中的模型引用
        /// </summary>
        private bool UpdateDrawingReference(string drawingPath, string newModelPath, string oldModelPath)
        {
            try
            {
                IModelDoc2 drawingDoc = (IModelDoc2)swApp.OpenDoc6(
                    drawingPath,
                    (int)swDocumentTypes_e.swDocDRAWING,
                    (int)swOpenDocOptions_e.swOpenDocOptions_Silent,
                    "", 0, 0);

                if (drawingDoc == null)
                {
                    Logger.Instance.Log($"无法打开工程图文件：{drawingPath}");
                    return false;
                }

                DrawingDoc docModel = drawingDoc as DrawingDoc;
                object[] views = (object[])docModel.GetViews();
                List<View> viewList = new List<View>();
                List<Component2> compList = new List<Component2>();

                // 遍历工程图视图
                for (int i = 0; i < views.Length; i++)
                {
                    var tempV = (object[])views[i];

                    if (tempV.Length > 1)
                    {
                        for (int j = 1; j < tempV.Length; j++)
                        {
                            var tempView = (View)tempV[j];
                            if (tempView.RootDrawingComponent.Component != null && tempView.RootDrawingComponent.Component.IGetModelDoc() != null)
                            {
                                if (tempView.RootDrawingComponent.Component.IGetModelDoc().GetPathName().ToUpper() == oldModelPath.ToUpper())
                                {
                                    viewList.Add(tempView);
                                    compList.Add(tempView.RootDrawingComponent.Component);
                                }

                            }
                            else
                            {
                                var visComps = (object[])tempView.GetVisibleComponents();

                                if (tempView.GetVisibleComponentCount() == 1 && ((visComps[0] as Component2).IGetModelDoc().GetPathName().ToUpper() == oldModelPath.ToUpper()))
                                {
                                    viewList.Add(tempView);
                                    compList.Add(visComps[0] as Component2);
                                }
                            }
                        }
                    }
                }

                // 更新工程图视图模型引用
                bool res = docModel.ReplaceViewModel(newModelPath, viewList.ToArray(), compList.ToArray());
                drawingDoc.Save();
                swApp.CloseDoc(drawingDoc.GetTitle());

                return res;
            }
            catch (Exception ex)
            {
                Logger.Instance.Log($"更新工程图引用时出现错误：{ex.Message}");
                return false;
            }
        }


    }
}
